﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using SharePoint.Orm.Helpers;

namespace SharePoint.Orm.Wrappers {
	/// <summary>
	/// A <see cref="SPUser"/> backed version of the <see cref="ISPOrmUser"/>
	/// </summary>
	public class SPOrmSharePointUser : ISPOrmUser {
		private readonly SPUser _user;
		private SPListItem _siteUserInfoListItem;

		/// <summary>
		/// constructor.
		/// </summary>
		/// <param name="user">The user to back the object with.</param>
		public SPOrmSharePointUser(SPUser user) {
			_user = user;
		}

		/// <summary>
		/// The id of the user.
		/// </summary>
		public virtual int Id {
			get { return _user.ID; }
		}

		/// <summary>
		/// The display name of the user.
		/// </summary>
		public virtual string Name {
			get { return _user.Name; }
		}

		/// <summary>
		/// The loginname of the user.
		/// </summary>
		public virtual string LoginName {
			get { return _user.LoginName; }
		}

		public virtual string Email {
			get { return _user.Email; }
		}

		public virtual PickerEntity ToPickerEntity() {
			return new PickerEntity {
				Key = LoginName
			};
		}

		/// <summary>
		/// The <see cref="SPUser"/>.
		/// </summary>
		/// <returns>The user.</returns>
		public SPPrincipal GetSPPrincipal() {
			return _user;
		}

		public virtual IEnumerable<ISPOrmGroup> GetGroups() {
			return _user.Groups.Cast<SPGroup>().Select(group => (ISPOrmGroup)new SPOrmSharePointGroup(group));
		}

		public virtual SPFieldUserValue GetSPFieldUserValue(SPDataContext ctx) {
			return new SPFieldUserValue(ctx.Site, _user.ID, _user.Name);
		}

		///<summary>
		/// Gets a property value from the SiteUserInfoList. eg Office.
		///</summary>
		///<param name="ctx">An open SPOrm data context</param>
		///<param name="propertyName">The name of the property to get (eg Office)</param>
		///<returns>The property value.</returns>
		///<exception cref="SPOrmException">If the user cannot be found.</exception>
		public virtual object GetSiteUserInfoPropertyValue(SPDataContext ctx, string propertyName) {
			if (_siteUserInfoListItem == null) {
				_siteUserInfoListItem = ctx.Site.Site.RootWeb.SiteUserInfoList.GetItemById(Id);
				if (_siteUserInfoListItem == null) {
					throw new SPOrmException("Could not find SiteUserInfo list item for user with id " + Id);
				}
			}
			return _siteUserInfoListItem[propertyName];
		}

		///<summary>
		/// Checks that the user is in at least one of the supplied groups.
		///</summary>
		///<param name="groups">The list of groups to check.</param>
		///<returns>true, if the user is in at least one of the groups. false, otherwise.</returns>
		public virtual bool IsInAtLeastOneGroup(IEnumerable<string> groups) {
			return SPUserHelper.IsUserInAtLeastOneGroup(_user, groups.ToArray());
		}
	}
}